package com.fbt.transfer.app.driver.util;

import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DownloadManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.core.content.FileProvider;
import cn.hutool.core.text.CharSequenceUtil;
import com.fbt.transfer.app.driver.model.AppUpdateConfig;
import com.fbt.transfer.app.driver.BuildConfig;
import com.fbt.transfer.app.driver.R;
import com.fbt.transfer.app.driver.http.AbstractCallback;
import com.fbt.transfer.app.driver.http.ApiClient;
import com.fbt.transfer.app.driver.model.AppQuery;
import java.io.File;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 检查应用更新
 *
 * @author tuocoo
 */
public class AppUpdateUtils {

  public static final String TAG = AppUpdateUtils.class.getSimpleName();
  private static final int CORE_POOL_SIZE = 1;
  private static final int MAX_POOL_SIZE = 1;
  private static final long KEEP_ALIVE_TIME = 60L;
  private static final TimeUnit TIME_UNIT = TimeUnit.SECONDS;
  private static final BlockingQueue<Runnable> WORK_QUEUE = new LinkedBlockingQueue<>();
  /**
   * ThreadFactory
   */
  private static final ThreadFactory THREAD_FACTORY = new ThreadFactory() {
    private final AtomicInteger threadNumber = new AtomicInteger(1);

    @Override
    public Thread newThread(Runnable r) {
      return new Thread(r, "AppUpdate-Thread-" + threadNumber.getAndIncrement());
    }
  };
  private static final ThreadPoolExecutor EXECUTOR_SERVICE = new ThreadPoolExecutor(
      CORE_POOL_SIZE,
      MAX_POOL_SIZE,
      KEEP_ALIVE_TIME,
      TIME_UNIT,
      WORK_QUEUE,
      THREAD_FACTORY
  );
  private static Dialog downloadDialog;
  private static DownloadManager downloadManager;
  private static long downloadId;
  private final AppUpdateConfig appConfig;
  private final Context context;
  
  // 权限请求码
  public static final int PERMISSION_WRITE_STORAGE = 2;
  public static final int PERMISSION_READ_STORAGE = 3;
  // 保存当前更新实例，用于权限回调后继续操作
  private static AppUpdateUtils currentInstance;

  private AppUpdateUtils(AppUpdateConfig appConfig, Context context) {
    this.appConfig = appConfig;
    this.context = context;
  }

  /**
   * 检查应用是否需要更新
   *
   * @param context 上下文
   */
  public static void checkAppUpdate(Context context) {
    ApiClient.getApiInterface()
        .checkUpdate(AppQuery.toMap())
        .enqueue(
            new AbstractCallback<>(context, false, false) {
              @Override
              protected void onSuccess(AppUpdateConfig appUpdateConfig) {
                AppUpdateUtils appUpdateUtils = new AppUpdateUtils(appUpdateConfig, context);
                int currentCode = BuildConfig.VERSION_CODE;
                if (appUpdateConfig.getVersionCode() > currentCode) {
                  if (Boolean.TRUE.equals(appUpdateConfig.getIsForceUpdate())) {
                    appUpdateUtils.startDownload();
                  } else {
                    appUpdateUtils.showOptionalUpdateDialog();
                  }
                } else {
                  Toast.makeText(context, "当前已是最新版本", Toast.LENGTH_SHORT).show();
                }
              }

            });
  }

  /**
   * 显示可选更新对话框
   */
  private void showOptionalUpdateDialog() {
    AlertDialog.Builder builder = new AlertDialog.Builder(context);
    builder.setTitle("发现新版本 " + appConfig.getCurrentVersion())
        .setMessage(appConfig.getUpdateDescription() != null ? appConfig.getUpdateDescription()
                        : "请更新应用以获得最新功能和改进，当前版本：" + BuildConfig.VERSION_NAME)
        .setPositiveButton(
            "更新", (dialog, which) -> startDownload())
        .setNegativeButton("取消", (dialog, which) -> dialog.dismiss());
    builder.setCancelable(true).create().show();
  }


  private BroadcastReceiver onDownloadComplete = null;

  /**
   * 开始下载APK
   */
  private void startDownload() {
    if (!(context instanceof Activity)) {
      LogUtils.e(TAG, "Context is not Activity, cannot start download");
      return;
    }
    // 保存当前实例，用于权限回调
    currentInstance = this;
    // 检查存储权限
    if (!checkPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, PERMISSION_WRITE_STORAGE)) {
      // 权限请求已发起，等待回调
      return;
    }
    // 权限已授予，继续下载流程
    continueDownload();
  }

  /**
   * 注册下载完成广播接收器
   */
  private void registerDownloadReceiver(Activity activity) {
    try {
      // 先注销之前的接收器
      unregisterDownloadReceiver();
      onDownloadComplete = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
          try {
            long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
            if (downloadId == id) {
              // 检查下载状态
              DownloadManager.Query query = new DownloadManager.Query();
              query.setFilterById(downloadId);
              Cursor cursor = null;
              try {
                cursor = downloadManager.query(query);
                if (cursor != null && cursor.moveToFirst()) {
                  int status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));
                  if (status == DownloadManager.STATUS_SUCCESSFUL) {
                    // 下载成功，开始安装
                    installApk(context);
                  } else {
                    // 下载失败
                    Toast.makeText(context, "下载失败，请重试", Toast.LENGTH_SHORT).show();
                  }
                }
              } finally {
                if (cursor != null) {
                  cursor.close();
                }
              }
            }
          } catch (Exception e) {
            LogUtils.e(TAG, "处理下载完成广播失败", e);
            Toast.makeText(context, "安装包处理失败", Toast.LENGTH_SHORT).show();
          } finally {
            unregisterDownloadReceiver();
          }
        }
      };
      activity.registerReceiver(
          onDownloadComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
    } catch (Exception e) {
      LogUtils.e(TAG, "注册下载完成广播接收器失败", e);
      Toast.makeText(activity, "下载监听注册失败", Toast.LENGTH_SHORT).show();
    }
  }

  private boolean checkPermission(String permission, int requestCode) {
    if (ContextCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
      // 申请权限
      ActivityCompat.requestPermissions((Activity) context, new String[]{permission}, requestCode);
      // 显示权限请求提示
      Toast.makeText(context, "请授予存储权限以继续下载", Toast.LENGTH_SHORT).show();
      return false;
    }
    return true;
  }
  
  /**
   * 处理权限请求结果
   * 在Activity的onRequestPermissionsResult中调用此方法
   *
   * @param requestCode  请求码
   * @param permissions  权限
   * @param grantResults 授权结果
   */
  public static void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    if (currentInstance == null) {
      return;
    }
    
    if (requestCode == PERMISSION_WRITE_STORAGE) {
      // 处理写存储权限
      if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
        // 权限已授予，继续下载
        currentInstance.continueDownload();
      } else {
        // 权限被拒绝
        Toast.makeText(currentInstance.context, "存储权限被拒绝，无法下载更新", Toast.LENGTH_SHORT).show();
      }
    } else if (requestCode == PERMISSION_READ_STORAGE) {
      // 处理读存储权限
      if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
        // 权限已授予，继续安装
        currentInstance.installApk(currentInstance.context);
      } else {
        // 权限被拒绝
        Toast.makeText(currentInstance.context, "存储权限被拒绝，无法安装更新", Toast.LENGTH_SHORT).show();
      }
    }
  }
  
  /**
   * 继续下载流程
   */
  private void continueDownload() {
    if (!(context instanceof Activity)) {
      return;
    }
    
    Activity activity = (Activity) context;
    
    // 检查网络状态
    if (!NetworkUtils.isNetworkAvailable(activity)) {
      Toast.makeText(activity, "网络不可用，请检查网络设置", Toast.LENGTH_SHORT).show();
      return;
    }
    
    // 权限已授予，开始下载
    try {
      downloadManager = (DownloadManager) activity.getSystemService(Context.DOWNLOAD_SERVICE);
      if (downloadManager == null) {
        Toast.makeText(activity, "下载服务不可用", Toast.LENGTH_SHORT).show();
        return;
      }

      String downloadUrl = appConfig.getDownloadUrl();
      if (CharSequenceUtil.isBlank(downloadUrl)) {
        Toast.makeText(activity, "下载地址无效", Toast.LENGTH_SHORT).show();
        return;
      }

      String fileName = downloadUrl.substring(downloadUrl.lastIndexOf("/") + 1);
      //检查该文件是否存在，存在就先删除
      File file = new File(
          Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), fileName);
      if (file.exists()) {
        file.delete();
      }

      DownloadManager.Request request = new DownloadManager.Request(Uri.parse(downloadUrl));
      request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
      request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName);
      request.setTitle("正在下载新版本");
      request.setDescription("请稍候...");

      downloadId = downloadManager.enqueue(request);
      if (downloadId == -1) {
        Toast.makeText(activity, "下载任务创建失败", Toast.LENGTH_SHORT).show();
        return;
      }

      showDownloadDialog();
      // 注册下载完成广播接收器
      registerDownloadReceiver(activity);
    } catch (Exception e) {
      LogUtils.e(TAG, "开始下载失败", e);
      Toast.makeText(activity, "开始下载失败，请重试", Toast.LENGTH_SHORT).show();
    }
  }

  /**
   * 注销下载完成广播接收器
   */
  private void unregisterDownloadReceiver() {
    try {
      if (onDownloadComplete != null) {
        context.unregisterReceiver(onDownloadComplete);
        onDownloadComplete = null;
      }
    } catch (Exception e) {
      LogUtils.e(TAG, "unregisterDownloadReceiver: ", e);
    }
  }

  /**
   * 显示下载对话框并更新进度
   */
  private void showDownloadDialog() {
    if (!(context instanceof Activity)) {
      LogUtils.e(TAG, "Context is not Activity, cannot show dialog");
      return;
    }

    Activity activity = (Activity) context;
    activity.runOnUiThread(() -> {
      try {
        downloadDialog = new Dialog(activity);
        downloadDialog.setCancelable(true);
        downloadDialog.setContentView(R.layout.dialog_download_progress);
        ProgressBar progressBar = downloadDialog.findViewById(R.id.progressBar);
        TextView textView = downloadDialog.findViewById(R.id.textViewProgress);
        Button cancelButton = downloadDialog.findViewById(R.id.buttonCancel);

        String downloadUrl = appConfig.getDownloadUrl();
        if (CharSequenceUtil.isBlank(downloadUrl)) {
          Toast.makeText(activity, "下载地址无效", Toast.LENGTH_SHORT).show();
          return;
        }
        String fileName = downloadUrl.substring(downloadUrl.lastIndexOf("/") + 1);

        cancelButton.setOnClickListener(v -> {
          if (downloadManager != null) {
            downloadManager.remove(downloadId);
          }
          if (downloadDialog != null && downloadDialog.isShowing()) {
            downloadDialog.dismiss();
          }
          File file = new File(
              Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),
              fileName
          );
          if (file.exists()) {
            file.delete();
          }
          // 取消下载时关闭线程池
          EXECUTOR_SERVICE.shutdownNow();
        });

        downloadDialog.show();

        // 使用线程池更新进度
        EXECUTOR_SERVICE.submit(() -> {
          try {
            while (!Thread.currentThread().isInterrupted()) {
              if (downloadManager == null) {
                break;
              }
              DownloadManager.Query query = new DownloadManager.Query();
              query.setFilterById(downloadId);
              Cursor cursor = null;
              try {
                cursor = downloadManager.query(query);
                if (cursor != null && cursor.moveToFirst()) {
                  int bytesDownloadedIndex = cursor.getColumnIndex(
                      DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR);
                  int bytesTotalIndex = cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES);
                  int statusIndex = cursor.getColumnIndex(DownloadManager.COLUMN_STATUS);

                  if (bytesDownloadedIndex == -1 || bytesTotalIndex == -1 || statusIndex == -1) {
                    break;
                  }

                  int bytesDownloaded = cursor.getInt(bytesDownloadedIndex);
                  int bytesTotal = cursor.getInt(bytesTotalIndex);
                  int progress = (int) ((bytesDownloaded * 100L) / bytesTotal);

                  activity.runOnUiThread(() -> {
                    if (downloadDialog != null && downloadDialog.isShowing() && progressBar != null
                        && textView != null) {
                      progressBar.setProgress(progress);
                      textView.setText(progress + "%");
                    }
                  });

                  if (cursor.getInt(statusIndex) == DownloadManager.STATUS_SUCCESSFUL) {
                    activity.runOnUiThread(() -> {
                      if (downloadDialog != null && downloadDialog.isShowing()) {
                        downloadDialog.dismiss();
                      }
                    });
                    break;
                  }
                }
              } finally {
                if (cursor != null) {
                  cursor.close();
                }
              }
              Thread.sleep(500); // 添加适当的延迟，避免过于频繁的查询
            }
          } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
          } catch (Exception e) {
            LogUtils.e(TAG, "更新下载进度失败", e);
          }
        });
      } catch (Exception e) {
        LogUtils.e(TAG, "显示下载对话框失败", e);
        Toast.makeText(activity, "显示下载对话框失败", Toast.LENGTH_SHORT).show();
      }
    });
  }


  /**
   * 安装APK
   *
   * @param mContext 上下文
   */
  private void installApk(Context mContext) {
    String downloadUrl = appConfig.getDownloadUrl();
    if (downloadUrl == null) {
      Toast.makeText(mContext, "下载地址为空", Toast.LENGTH_SHORT).show();
      return;
    }
    String fileName = downloadUrl.substring(downloadUrl.lastIndexOf("/") + 1);
    File file = new File(
        Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), fileName);
    if (file.exists()) {
      // 保存当前实例，用于权限回调
      currentInstance = this;
      // 检查读取外部存储权限
      if (!checkPermission(Manifest.permission.READ_EXTERNAL_STORAGE, PERMISSION_READ_STORAGE)) {
        return;
      }
      try {
        Uri apkUri = FileProvider.getUriForFile(mContext, BuildConfig.APPLICATION_ID + ".fileprovider", file);
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

        // 检查是否有Activity可以处理这个Intent
        if (intent.resolveActivity(mContext.getPackageManager()) != null) {
          mContext.startActivity(intent);
          // 延迟退出应用，给用户时间看到安装界面
          new Handler(Looper.getMainLooper()).postDelayed(() -> {
            if (mContext instanceof Activity) {
              ((Activity) mContext).finish();
            }
            System.exit(0);
          }, 1000);
        } else {
          Toast.makeText(mContext, "无法安装应用，请检查您的设备设置", Toast.LENGTH_SHORT).show();
        }
      } catch (Exception e) {
        LogUtils.e(TAG, "安装APK失败", e);
        Toast.makeText(mContext, "安装失败，请重试", Toast.LENGTH_SHORT).show();
      }
    } else {
      Toast.makeText(mContext, "下载失败，请重试", Toast.LENGTH_SHORT).show();
    }
  }

}
